/**
 * @file ThreadPool.cpp
 * @author your name (you@domain.com)
 * @brief 
 * @version 0.1
 * @date 2025-06-03
 * 
 * @copyright Copyright (c) 2025
 * 
 * 为什么需要线程池？
 * (1) 创建和销毁线程的开销很大，线程池避免了这种重复成本
 * (2) 限制同时运行的线程数量，防止系统资源耗尽
 * 
 */

#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>
#include <stdexcept>

class ThreadPool {
public:
    // 构造函数，启动指定数量的工作线程
    explicit ThreadPool(size_t threads = std::thread::hardware_concurrency())
        : stop(false) {
        if(threads == 0) threads = 4; // 默认4线程
        for(size_t i = 0; i < threads; ++i) {
            workers.emplace_back([this] {
                for(;;) {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> lock(this->queue_mutex);
                        this->condition.wait(lock, 
                            [this]{ return this->stop || !this->tasks.empty(); });
                        
                        // 停止且任务队列为空时退出
                        if(this->stop && this->tasks.empty())
                            return;
                            
                        task = std::move(this->tasks.front());
                        this->tasks.pop();
                    }
                    try {
                        task(); // 执行任务
                    } catch(...) {
                        // 异常处理（可扩展为日志记录）
                        std::cerr << "Task execution failed with exception\n";
                    }
                }
            });
        }
    }

    // 提交任务到线程池（支持任意参数类型和返回类型）
    template<class F, class... Args>
    auto enqueue(F&& f, Args&&... args) 
        -> std::future<typename std::result_of<F(Args...)>::type> {
        using return_type = typename std::result_of<F(Args...)>::type;

        auto task = std::make_shared<std::packaged_task<return_type()>>(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...)
        );
        
        std::future<return_type> res = task->get_future();
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            if(stop)
                throw std::runtime_error("enqueue on stopped ThreadPool");
                
            tasks.emplace([task](){ (*task)(); });
        }
        condition.notify_one();
        return res;
    }

    // 析构函数：等待所有任务完成
    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            stop = true;
        }
        condition.notify_all();
        for(std::thread &worker : workers)
            if(worker.joinable())
                worker.join();
    }

private:
    std::vector<std::thread> workers;  // 工作线程集合
    std::queue<std::function<void()>> tasks; // 任务队列
    
    std::mutex queue_mutex; // 队列同步锁
    std::condition_variable condition; // 条件变量
    bool stop; // 停止标志
};

// 使用示例
int main() {
    ThreadPool pool(4); // 创建4线程的线程池

    // 提交多个任务
    std::vector<std::future<int>> results;
    for(int i = 0; i < 8; ++i) {
        results.emplace_back(
            pool.enqueue([i] {
                std::cout << "Task " << i << " started\n";
                std::this_thread::sleep_for(std::chrono::seconds(1));
                std::cout << "Task " << i << " finished\n";
                return i*i;
            })
        );
    }

    // 获取结果
    for(auto&& result : results)
        std::cout << "Result: " << result.get() << std::endl;

    return 0;
}
